library(RUnit)

# it is assumed the tests are executed in the parent directory
#source("../R/emBAM.R")
# disable multicore for testing
#options("cores"=1)


bam.files <- c("../inst/extdata/toy.bam","../inst/extdata/se.tophat.bam","../inst/extdata/pe.tophat.bam","../inst/extdata/pe2.tophat.bam")
# generate a index for each file
#lapply(bam.files,em.bam.index.file)

##############################
# Aux. functions
# Check if two lists are equal
equal.list <- function(l1,l2) {
  return(prod(serialize(l1,NULL)==serialize(l2,NULL))==TRUE)
}

#######
# Utils
test.mergeSumLists <- function() {

  test1<-list(list(count=c(99)),list(count=c(1)),list(count=c(2)))
  test2<-list(list(count=c(99,99)),list(count=c(1,1)),list(count=c(2,2)))
  test3<-list(list(count=c(99,99)),list(count=c(3)),list(count=c(3)))
  names(test3[[1]]$count)<-c("x1","x2")
  names(test3[[2]]$count)<-c("x1")
  names(test3[[3]]$count)<-c("x2")
  
  checkTrue(unlist(mergeSumLists(test1))==c(102))
  checkTrue(prod(unlist(mergeSumLists(test2))==c(102,102))==TRUE)
  checkTrue(prod(unlist(mergeSumLists(test3))==c(102,102))==TRUE)
}

test.mergeLists <- function() {

  test1<-list(list(count=c(99)),list(count=c(1)),list(count=c(2)))
  test2<-list(list(count=c(99,99)),list(count=c(1,1)),list(count=c(2,2)))
  test3<-list(list(count=c(99,99)),list(count=c(3)),list(count=c(3)))
  names(test3[[1]]$count)<-c("x1","x2")
  names(test3[[2]]$count)<-c("x1")
  names(test3[[3]]$count)<-c("x2")
  
  checkTrue(prod(unlist(mergeLists(test1))==c(99,1,2))==TRUE)
  checkTrue(prod(unlist(mergeLists(test2))==c(99,99,1,1,2,2))==TRUE)
  checkTrue(prod(unlist(mergeLists(test3))==c(99,99,3,3))==TRUE)
}

test.resultlist2count <- function() {
  checkTrue(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C"))))==3)
  checkTrue(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C"))),field="a")==3)
  checkTrue(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C","D"))),"a")==3)
  checkTrue(prod(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C"))),field="a",distinct=T)==c(1,1,1))==TRUE)
  checkTrue(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C","D"))),"b")==4)
  checkTrue(prod(resultlist2count(list(list(a=c(1,2,3),b=c("A","B","C","D"))),"b",distinct=TRUE)==c(1,1,1,1))==TRUE)
}
#
test.countInVector <- function() {
  checkTrue(is.na(countInVector("nop",1,c(1,1,2,1))))
  checkTrue(countInVector("=",1,c(1,1,2,1))==3)
  checkTrue(countInVector("eq",1,c(1,1,2,1))==3)
  checkTrue(countInVector(">",1,c(1,1,2,1))==1)
  checkTrue(countInVector("gt",1,c(1,1,2,1))==1)
  checkTrue(countInVector("<",1,c(1,1,2,1))==0)
  checkTrue(countInVector("<=",1,c(1,1,2,1))==3)
}

###############
#
#
test.bam.flavour.data <- function() {
  checkTrue(is.na(bam.flavour.data(bam.files[1])))
}

###############
# API
refs <- list()
refs[[bam.files[1]]] <- c("ref","ref2")
test.refsFromBam <- function() {

  checkException(em.refsFromBam())
  checkTrue(is.null(em.refsFromBam(1)))
  
  qtest <- function(file) {
    checkTrue(prod(em.refsFromBam(file)==refs[[file]])==1,msg=file)
  }
  lapply(bam.files[1],qtest)
}
# 
test.bam.flavour <- function() {
  checkTrue(is.na(em.bam.flavour(bam.files[1])))
}

test.em.query <- function() {
  ql <- list("1"=em.query(),"2"=em.query("All e"),"3"=em.query("Paire"),"4"=em.query("Paired"))
  ql.res <- list("1"=list(where=NULL,count=NULL,param=ScanBamParam(flag=scanBamFlag(isUnmappedQuery=NA))),
                 "2"=list(where=NULL,count=NULL,param=ScanBamParam(flag=scanBamFlag(isUnmappedQuery=NA))),
                 "3"=NULL,
                 "4"=list(where=NULL,count=NULL, param=ScanBamParam(flag=scanBamFlag(isUnmappedQuery=FALSE,isValidVendorRead=TRUE,isPaired=TRUE))))
  for (n in names(ql)) {
    checkTrue(equal.list(ql[[n]],ql.res[[n]]))
  }
}


################
# em.countBam
em.count <- list()
em.count[[bam.files[1]]] <- c(NA,NA,NA,NA,"toy.bam","12","207")
em.count[[bam.files[2]]] <- c(NA,NA,NA,NA,"se.tophat.bam","185262","6498135")
em.count[[bam.files[3]]] <- c(NA,NA,NA,NA,"pe.tophat.bam","10353","517650")
em.count[[bam.files[4]]] <- c(NA,NA,NA,NA,"pe2.tophat.bam","5849","292450")
# simple counts (all entries)
test.em.countBam <- function() {
  q <- em.query()
  qtest <- function(file,query) {
    v <- em.countBam(file=file,query=query)      
    res <- v[5:7]==em.count[[file]][5:7]
    checkTrue(prod(res,na.rm=T)==1,msg=paste(file," ",res,sep=""))
  }
  lapply(bam.files,qtest,q)
}
####################
test.em.scanBam <- function() {
  q <- em.query()
  qtest <- function(file,query) {
    checkTrue(is.list(em.scanBam(file=file,query=query)))
  }
  lapply(bam.files,qtest,q)
}
###################

test.em.scanBamGrep <- function() {
  queries <- list(q1=em.query(where=list(c("grep","cigar","N")),count="*"),
                  q2=em.query(where=list(c("grep","cigar","H")),count="*"),
                  q3=em.query(where=list(c("grep","cigar","M")),count="*"))
  q.res <- list()
  q.res[[bam.files[1]]] <- list(q1=c(1),q2=c(2),q3=c(12))
  q.res[[bam.files[2]]] <- list(q1=c(89),q2=c(0),q3=c(185262))
  q.res[[bam.files[3]]] <- list(q1=c(1611),q2=c(0),q3=c(10353))
  q.res[[bam.files[4]]] <- list(q1=c(949),q2=c(0),q3=c(5849))
  qtest <- function(test,file,exp.res) {
    q <- queries[[test]]
    res <- exp.res[[test]]
    checkTrue(em.scanBam(file=file,query=q)==res)
  }

  for ( f in bam.files) {
     lapply(names(queries),qtest,f,q.res[[f]])
  }
  qtest2 <- function(file,query,res) {
    print(file)
    print(em.scanBam(file=file,query=query))
    checkTrue(em.scanBam(file=file,query=query)$count==res)
  }
  q<- em.query(where=list(c("grep","cigar","M")),count="M")
  lapply(bam.files[2:4],qtest2,q,0)
}

test.em.scanBamComp <- function() {
  
  test.queries <- list(q1=em.query(what="mpos",where=list(c(">","mpos",7)),count="*"),
                       q2=em.query(what="mpos",where=list(c("=","mpos",0)),count="*"),
                       q3=em.query(what="mpos",where=list(c("!=","mpos",0)),count="*"),
                       q4=em.query(what="mpos",where=list(c(">=","mpos",0)),count=c("distinct","mpos")),
                       q5=em.query(what="mpos",where=list(c("eq","mpos",37)),count=c("mpos")),
                       q6=em.query(what="mpos",where=list(c("<","mpos",7)),count=c("mpos")),
                       q7=em.query(what="mpos",where=list(c("<=","mpos",7)),count=c("mpos"))
                       )
  test.res <- list()
  test.res[[bam.files[1]]] <- list(q1=c(1),
                                   q2=c(10),
                                   q3=c(2),
                                   q4=c(10,1,1),
                                   q5=c(1),
                                   q6=c(10),
                                   q7=c(11)
                                )
  qtest <- function(test,file,exp.res) {
    q <- test.queries[[test]]
    res <- exp.res[[test]]
    checkTrue(prod(unlist(em.scanBam(file=file,query=q))==res)==TRUE,msg=paste("Test: ",test,"  expected res:",res,sep=""))
  }

  for ( f in bam.files) {
     lapply(names(test.queries),qtest,f,test.res[[f]])
   }
}


####################
test.bam.counts.df <- function() {
  qtest <- function(file) {
    checkTrue(is.data.frame(em.bam.counts.df(file,use.cache=F)))
    checkTrue(is.data.frame(em.bam.counts.df(file,use.cache=T)))
    checkTrue(is.data.frame(em.bam.counts.df(file,use.cache=F,num.reads=100000)))
  }
  lapply(bam.files,qtest,q)
}

#bam.counts.df

#bam.index.prefix

# bam.sum.stats.table

# bam.readsperseq.table

# bam.pe.isize

## testResult <- runTestSuite(testsuite.myBAM)
## printTextProtocol(testResult)
## runTestFile(file.path(.path.package(package="RUnit"),
## "examples/runitc2f.r"))
